package com.kotle.baselib.retfofit;


import android.content.Context;
import android.text.TextUtils;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by kotle on 2017/7/3.
 * 网络请求的工具类
 */

public class NetUtil {
    private static String mBaseUrl;
    private static Object netApiWithGson;//默认的BaseUrl，请求结果转换为JavaBean
    private static Object netApiNoGson;//默认的BaseUrl，请求结果不转换为JavaBean
    private static Class<?> mNetClass;


    /**
     * 一般的默认操作
     * 获取retrofit
     * 使用默认的BASE_URL
     * 响应体转换为JavaBean
     *
     * @return 返回retrofit对象
     */
    private static Object getNetApi(boolean isNewObject, OkHttpClient client) {
        if (netApiWithGson == null || isNewObject) {
            Retrofit.Builder builder = new Retrofit.Builder()
                    .baseUrl(mBaseUrl);
            if (client != null) {
                builder.client(client);
            }
            netApiWithGson = builder
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build().create(mNetClass);
        }
        return netApiWithGson;
    }

    /**
     * 获取retrofit
     * 使用默认的BASE_URL
     * 不转换响应体
     *
     * @return 返回retrofit对象
     */
    private static Object getNetApiNoGson(boolean isNewObject, OkHttpClient client) {
        if (netApiNoGson == null || isNewObject) {
            Retrofit.Builder builder = new Retrofit.Builder()
                    .baseUrl(mBaseUrl);
            if (client != null) {
                builder.client(client);
            }
            netApiNoGson = builder
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build().create(mNetClass);
        }
        return netApiNoGson;
    }

    /**
     * 获取retrofit，由于baseUrl不同，所以每次需要new一个新对象
     * 使用自定义的BaseUrl
     * 响应体转换为JavaBean
     *
     * @return 返回retrofit对象
     */
    private static Object getNetApi(String baseUrl, OkHttpClient client) {
        Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(baseUrl);
        if (client != null) {
            builder.client(client);
        }
        return builder
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build().create(mNetClass);
    }

    /**
     * 获取retrofit，由于baseUrl可能不同，所以每次需要new一个新对象
     * 使用自定义的BaseUrl
     * 响应体不转换
     *
     * @return 返回retrofit对象
     */
    private static Object getNetApiNoGson(String BaseUrl, OkHttpClient client) {
        Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(BaseUrl);
        if (client != null) {
            builder.client(client);
        }
        return builder
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build().create(mNetClass);
    }

    /**
     * 发送网络请求，由于baseUrl和netClass,<P> 一般为固定，建议使用者新建一个工具类
     *
     * @param context  上下文，可以为null
     * @param baseUrl  Api接口的通用部分，可null，如果为null，则必须重载{@link NetRequestCall}的{getBaseUrl()}方法
     * @param netClass Api书写访问网络方法的接口
     * @param call     网络请求回调
     * @param <T>      返回数据类型，参考{netClass}
     * @param <P>      netClass
     */
    @SuppressWarnings("unchecked")
    public static <T, P> void sendNetRequest(final Context context, final String baseUrl, final Class<P> netClass, final NetRequestCall<T, P> call) {
        if (call == null) {
            return;
        }
        Observable.create(new ObservableOnSubscribe<Observable<T>>() {
            @Override
            public void subscribe(ObservableEmitter<Observable<T>> observableEmitter) throws Exception {
                boolean isNewObject = false;
                if ((!TextUtils.isEmpty(baseUrl) && !baseUrl.equals(mBaseUrl))) {
                    mBaseUrl = baseUrl;
                    isNewObject = true;
                }
                if (netClass != null && netClass != mNetClass) {
                    mNetClass = netClass;
                    isNewObject = true;
                }
                Observable<T> observable;
                String url = call.getBaseUrl();
                if (TextUtils.isEmpty(url)) {
                    if (call.isSwithJavaBean()) {
                        observable = call.getObservable((P) getNetApi(isNewObject, call.getOkHttpClient()));
                    } else {
                        observable = call.getObservable((P) getNetApiNoGson(isNewObject, call.getOkHttpClient()));
                    }
                } else {
                    if (call.isSwithJavaBean()) {
                        observable = call.getObservable((P) getNetApi(url, call.getOkHttpClient()));
                    } else {
                        observable = call.getObservable((P) getNetApiNoGson(url, call.getOkHttpClient()));
                    }
                }
                observableEmitter.onNext(observable);
            }
        })
                .subscribeOn(Schedulers.newThread())
                .subscribe(new Consumer<Observable<T>>() {
                    @Override
                    public void accept(Observable<T> tObservable) throws Exception {
                        tObservable.subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribeWith(new BaseSubscriberResultNoLimit<>(call, context));
                    }
                });
    }
}
